From: Florian Müllner Date: Thu, 25 Jul 2019 16:53:00 +0000 (+0200) Subject: js: Actorize animated objects X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~839^2^2~49 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=3d3dca4aa;p=gnome-shell.git js: Actorize animated objects We have a couple of places where we don't tween the actor, but a custom property on the delegate object. In order to move those to Clutter animations, we will need an animatable, so turn those objects into widget subclasses. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666 --- diff --git a/js/ui/barLevel.js b/js/ui/barLevel.js index 7b3d89213..90fd20b62 100644 --- a/js/ui/barLevel.js +++ b/js/ui/barLevel.js @@ -1,37 +1,48 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* exported BarLevel */ -const { Atk, Clutter, St } = imports.gi; -const Signals = imports.signals; - -var BarLevel = class { - constructor(value, params = {}) { - if (isNaN(value)) - // Avoid spreading NaNs around - throw TypeError('The bar level value must be a number'); +const { Atk, Clutter, GObject, St } = imports.gi; + +var BarLevel = GObject.registerClass({ + Properties: { + 'value': GObject.ParamSpec.double( + 'value', 'value', 'value', + GObject.ParamFlags.READWRITE, + 0, 1, 0), + 'maximum-value': GObject.ParamSpec.double( + 'maximum-value', 'maximum-value', 'maximum-value', + GObject.ParamFlags.READWRITE, + 1, 2, 1), + 'overdrive-start': GObject.ParamSpec.double( + 'overdrive-start', 'overdrive-start', 'overdrive-start', + GObject.ParamFlags.READWRITE, + 1, 2, 1) + } +}, class BarLevel extends St.DrawingArea { + _init(params) { this._maxValue = 1; - this._value = Math.max(Math.min(value, this._maxValue), 0); + this._value = 0; this._overdriveStart = 1; this._barLevelWidth = 0; - this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel', - can_focus: params['canFocus'] || false, - reactive: params['reactive'] || false, - accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR }); - this.actor.connect('repaint', this._barLevelRepaint.bind(this)); - this.actor.connect('allocation-changed', (actor, box) => { + let defaultParams = { + style_class: 'barlevel', + accessible_role: Atk.Role.LEVEL_BAR + }; + super._init(Object.assign(defaultParams, params)); + this.connect('allocation-changed', (actor, box) => { this._barLevelWidth = box.get_width(); }); - this._customAccessible = St.GenericAccessible.new_for_actor(this.actor); - this.actor.set_accessible(this._customAccessible); + this._customAccessible = St.GenericAccessible.new_for_actor(this); + this.set_accessible(this._customAccessible); this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this)); this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this)); this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this)); this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this)); - this.connect('value-changed', this._valueChanged.bind(this)); + this.connect('notify::value', this._valueChanged.bind(this)); } get value() { @@ -39,16 +50,15 @@ var BarLevel = class { } set value(value) { - if (isNaN(value)) - throw TypeError('The bar level value must be a number'); - value = Math.max(Math.min(value, this._maxValue), 0); if (this._value == value) return; this._value = value; - this.actor.queue_repaint(); + this._value = value; + this.notify('value'); + this.queue_repaint(); } // eslint-disable-next-line camelcase @@ -58,9 +68,6 @@ var BarLevel = class { // eslint-disable-next-line camelcase set maximum_value(value) { - if (isNaN(value)) - throw TypeError('The bar level max value must be a number'); - value = Math.max(value, 1); if (this._maxValue == value) @@ -68,7 +75,8 @@ var BarLevel = class { this._maxValue = value; this._overdriveStart = Math.min(this._overdriveStart, this._maxValue); - this.actor.queue_repaint(); + this.notify('maximum-value'); + this.queue_repaint(); } // eslint-disable-next-line camelcase @@ -78,9 +86,6 @@ var BarLevel = class { // eslint-disable-next-line camelcase set overdrive_start(value) { - if (isNaN(value)) - throw TypeError('The overdrive limit value must be a number'); - if (this._overdriveStart == value) return; @@ -89,13 +94,14 @@ var BarLevel = class { `which is a number greater than the maximum allowed value ${this._maxValue}`); this._overdriveStart = value; - this.actor.queue_repaint(); + this.notify('overdrive-start'); + this.queue_repaint(); } - _barLevelRepaint(area) { - let cr = area.get_context(); - let themeNode = area.get_theme_node(); - let [width, height] = area.get_surface_size(); + vfunc_repaint() { + let cr = this.get_context(); + let themeNode = this.get_theme_node(); + let [width, height] = this.get_surface_size(); let barLevelHeight = themeNode.get_length('-barlevel-height'); let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2; @@ -225,5 +231,4 @@ var BarLevel = class { _valueChanged() { this._customAccessible.notify("accessible-value"); } -}; -Signals.addSignalMethods(BarLevel.prototype); +}); diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js index f8e929165..743778389 100644 --- a/js/ui/keyboard.js +++ b/js/ui/keyboard.js @@ -570,11 +570,21 @@ var FocusTracker = class { }; Signals.addSignalMethods(FocusTracker.prototype); -var EmojiPager = class EmojiPager { - constructor(sections, nCols, nRows) { - this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(), - reactive: true, - clip_to_allocation: true }); +var EmojiPager = GObject.registerClass({ + Signals: { + 'emoji': { param_types: [GObject.TYPE_STRING] }, + 'page-changed': { + param_types: [GObject.TYPE_INT, GObject.TYPE_INT, GObject.TYPE_INT] + } + } +}, class EmojiPager extends St.Widget { + _init(sections, nCols, nRows) { + super._init({ + layout_manager: new Clutter.BinLayout(), + reactive: true, + clip_to_allocation: true + }); + this._sections = sections; this._nCols = nCols; this._nRows = nRows; @@ -596,7 +606,7 @@ var EmojiPager = class EmojiPager { panAction.connect('gesture-cancel', this._onPanCancel.bind(this)); panAction.connect('gesture-end', this._onPanEnd.bind(this)); this._panAction = panAction; - this.actor.add_action(panAction); + this.add_action(panAction); } get delta() { @@ -626,8 +636,8 @@ var EmojiPager = class EmojiPager { if (followingPage != null) { this._followingPanel = this._generatePanel(followingPage); this._followingPanel.set_pivot_point(0.5, 0.5); - this.actor.add_child(this._followingPanel); - this.actor.set_child_below_sibling(this._followingPanel, this._panel); + this.add_child(this._followingPanel); + this.set_child_below_sibling(this._followingPanel, this._panel); } this._followingPage = followingPage; @@ -675,12 +685,12 @@ var EmojiPager = class EmojiPager { } _onPanBegin() { - this._width = this.actor.width; + this._width = this.width; return true; } _onPanEnd() { - if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) { + if (Math.abs(this._delta) < this.width * PANEL_SWITCH_RELATIVE_DISTANCE) { this._onPanCancel(); } else { let value; @@ -705,7 +715,7 @@ var EmojiPager = class EmojiPager { } _onPanCancel() { - let relDelta = Math.abs(this._delta) / this.actor.width; + let relDelta = Math.abs(this._delta) / this.width; let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta); Tweener.removeTweens(this); @@ -823,7 +833,7 @@ var EmojiPager = class EmojiPager { if (!this._panel) { this._panel = this._generatePanel(nPage); - this.actor.add_child(this._panel); + this.add_child(this._panel); } let page = this._pages[nPage]; @@ -840,8 +850,7 @@ var EmojiPager = class EmojiPager { } } } -}; -Signals.addSignalMethods(EmojiPager.prototype); +}); var EmojiSelection = class EmojiSelection { constructor() { diff --git a/js/ui/osdWindow.js b/js/ui/osdWindow.js index d2656a560..cdcd36a18 100644 --- a/js/ui/osdWindow.js +++ b/js/ui/osdWindow.js @@ -66,8 +66,11 @@ var OsdWindow = class { this._label = new St.Label(); this._box.add(this._label); - this._level = new BarLevel.BarLevel(0, { styleClass: 'level' }); - this._box.add(this._level.actor); + this._level = new BarLevel.BarLevel({ + style_class: 'level', + value: 0 + }); + this._box.add(this._level); this._hideTimeoutId = 0; this._reset(); @@ -107,7 +110,7 @@ var OsdWindow = class { } setLevel(value) { - this._level.actor.visible = (value != undefined); + this._level.visible = (value != undefined); if (value != undefined) { if (this.actor.visible) Tweener.addTween(this._level, diff --git a/js/ui/slider.js b/js/ui/slider.js index cfce0cccc..7672cf67e 100644 --- a/js/ui/slider.js +++ b/js/ui/slider.js @@ -1,27 +1,31 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* exported Slider */ -const { Atk, Clutter } = imports.gi; -const Signals = imports.signals; +const { Atk, Clutter, GObject } = imports.gi; const BarLevel = imports.ui.barLevel; var SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */ -var Slider = class extends BarLevel.BarLevel { - constructor(value) { - let params = { - styleClass: 'slider', - canFocus: true, +var Slider = GObject.registerClass({ + Signals: { + 'drag-begin': {}, + 'drag-end': {} + } +}, class Slider extends BarLevel.BarLevel { + _init(value) { + super._init({ + value, + style_class: 'slider', + can_focus: true, reactive: true, - accessibleRole: Atk.Role.SLIDER, - }; - super(value, params); + accessible_role: Atk.Role.SLIDER + }); - this.actor.connect('button-press-event', this._startDragging.bind(this)); - this.actor.connect('touch-event', this._touchDragging.bind(this)); - this.actor.connect('scroll-event', this._onScrollEvent.bind(this)); - this.actor.connect('key-press-event', this.onKeyPressEvent.bind(this)); + this.connect('button-press-event', this._startDragging.bind(this)); + this.connect('touch-event', this._touchDragging.bind(this)); + this.connect('scroll-event', this._onScrollEvent.bind(this)); + this.connect('key-press-event', this.onKeyPressEvent.bind(this)); this._releaseId = this._motionId = 0; this._dragging = false; @@ -29,13 +33,13 @@ var Slider = class extends BarLevel.BarLevel { this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this)); } - _barLevelRepaint(area) { - super._barLevelRepaint(area); + vfunc_repaint() { + super.vfunc_repaint(); // Add handle - let cr = area.get_context(); - let themeNode = area.get_theme_node(); - let [width, height] = area.get_surface_size(); + let cr = this.get_context(); + let themeNode = this.get_theme_node(); + let [width, height] = this.get_surface_size(); let handleRadius = themeNode.get_length('-slider-handle-radius'); @@ -72,20 +76,20 @@ var Slider = class extends BarLevel.BarLevel { let sequence = event.get_event_sequence(); if (sequence != null) - device.sequence_grab(sequence, this.actor); + device.sequence_grab(sequence, this); else - device.grab(this.actor); + device.grab(this); this._grabbedDevice = device; this._grabbedSequence = sequence; if (sequence == null) { - this._releaseId = this.actor.connect('button-release-event', this._endDragging.bind(this)); - this._motionId = this.actor.connect('motion-event', this._motionEvent.bind(this)); + this._releaseId = this.connect('button-release-event', this._endDragging.bind(this)); + this._motionId = this.connect('motion-event', this._motionEvent.bind(this)); } // We need to emit 'drag-begin' before moving the handle to make - // sure that no 'value-changed' signal is emitted before this one. + // sure that no 'notify::value' signal is emitted before this one. this.emit('drag-begin'); let absX, absY; @@ -97,9 +101,9 @@ var Slider = class extends BarLevel.BarLevel { _endDragging() { if (this._dragging) { if (this._releaseId) - this.actor.disconnect(this._releaseId); + this.disconnect(this._releaseId); if (this._motionId) - this.actor.disconnect(this._motionId); + this.disconnect(this._motionId); if (this._grabbedSequence != null) this._grabbedDevice.sequence_ungrab(this._grabbedSequence); @@ -153,8 +157,8 @@ var Slider = class extends BarLevel.BarLevel { this._value = Math.min(Math.max(0, this._value + delta), this._maxValue); - this.actor.queue_repaint(); - this.emit('value-changed', this._value); + this.queue_repaint(); + this.notify('value'); return Clutter.EVENT_STOP; } @@ -174,9 +178,9 @@ var Slider = class extends BarLevel.BarLevel { if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) { let delta = key == Clutter.KEY_Right ? 0.1 : -0.1; this._value = Math.max(0, Math.min(this._value + delta, this._maxValue)); - this.actor.queue_repaint(); + this.queue_repaint(); this.emit('drag-begin'); - this.emit('value-changed', this._value); + this.notify('value'); this.emit('drag-end'); return Clutter.EVENT_STOP; } @@ -185,11 +189,11 @@ var Slider = class extends BarLevel.BarLevel { _moveHandle(absX, _absY) { let relX, sliderX; - [sliderX] = this.actor.get_transformed_position(); + [sliderX] = this.get_transformed_position(); relX = absX - sliderX; let width = this._barLevelWidth; - let handleRadius = this.actor.get_theme_node().get_length('-slider-handle-radius'); + let handleRadius = this.get_theme_node().get_length('-slider-handle-radius'); let newvalue; if (relX < handleRadius) @@ -199,12 +203,11 @@ var Slider = class extends BarLevel.BarLevel { else newvalue = (relX - handleRadius) / (width - 2 * handleRadius); this._value = newvalue * this._maxValue; - this.actor.queue_repaint(); - this.emit('value-changed', this._value); + this.queue_repaint(); + this.notify('value'); } _getMinimumIncrement() { return 0.1; } -}; -Signals.addSignalMethods(Slider.prototype); +}); diff --git a/js/ui/status/brightness.js b/js/ui/status/brightness.js index ff31ef8df..16c1e9dbb 100644 --- a/js/ui/status/brightness.js +++ b/js/ui/status/brightness.js @@ -33,13 +33,13 @@ var Indicator = class extends PanelMenu.SystemIndicator { this.menu.addMenuItem(this._item); this._slider = new Slider.Slider(0); - this._slider.connect('value-changed', this._sliderChanged.bind(this)); - this._slider.actor.accessible_name = _("Brightness"); + this._slider.connect('notify::value', this._sliderChanged.bind(this)); + this._slider.accessible_name = _("Brightness"); let icon = new St.Icon({ icon_name: 'display-brightness-symbolic', style_class: 'popup-menu-icon' }); this._item.add(icon); - this._item.add(this._slider.actor, { expand: true }); + this._item.add(this._slider, { expand: true }); this._item.connect('button-press-event', (actor, event) => { return this._slider.startDragging(event); }); @@ -49,8 +49,8 @@ var Indicator = class extends PanelMenu.SystemIndicator { } - _sliderChanged(slider, value) { - let percent = value * 100; + _sliderChanged() { + let percent = this._slider.value * 100; this._proxy.Brightness = percent; } diff --git a/js/ui/status/volume.js b/js/ui/status/volume.js index 4f0270f9b..8ab001cd8 100644 --- a/js/ui/status/volume.js +++ b/js/ui/status/volume.js @@ -36,12 +36,12 @@ var StreamSlider = class { this._soundSettings.connect(`changed::${ALLOW_AMPLIFIED_VOLUME_KEY}`, this._amplifySettingsChanged.bind(this)); this._amplifySettingsChanged(); - this._slider.connect('value-changed', this._sliderChanged.bind(this)); + this._slider.connect('notify::value', this._sliderChanged.bind(this)); this._slider.connect('drag-end', this._notifyVolumeChange.bind(this)); this._icon = new St.Icon({ style_class: 'popup-menu-icon' }); this.item.add(this._icon); - this.item.add(this._slider.actor, { expand: true }); + this.item.add(this._slider, { expand: true }); this.item.connect('button-press-event', (actor, event) => { return this._slider.startDragging(event); }); @@ -99,10 +99,11 @@ var StreamSlider = class { return this._slider.scroll(event); } - _sliderChanged(slider, value) { + _sliderChanged() { if (!this._stream) return; + let value = this._slider.value; let volume = value * this._control.get_vol_max_norm(); let prevMuted = this._stream.is_muted; if (volume < 1) { @@ -189,7 +190,7 @@ Signals.addSignalMethods(StreamSlider.prototype); var OutputStreamSlider = class extends StreamSlider { constructor(control) { super(control); - this._slider.actor.accessible_name = _("Volume"); + this._slider.accessible_name = _("Volume"); } _connectStream(stream) { @@ -237,7 +238,7 @@ var OutputStreamSlider = class extends StreamSlider { var InputStreamSlider = class extends StreamSlider { constructor(control) { super(control); - this._slider.actor.accessible_name = _("Microphone"); + this._slider.accessible_name = _("Microphone"); this._control.connect('stream-added', this._maybeShowInput.bind(this)); this._control.connect('stream-removed', this._maybeShowInput.bind(this)); this._icon.icon_name = 'audio-input-microphone-symbolic'; diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js index c4e397edf..51026499a 100644 --- a/js/ui/workspaceThumbnail.js +++ b/js/ui/workspaceThumbnail.js @@ -244,21 +244,24 @@ var ThumbnailState = { /** * @metaWorkspace: a #Meta.Workspace */ -var WorkspaceThumbnail = class { - constructor(metaWorkspace) { +var WorkspaceThumbnail = GObject.registerClass( +class WorkspaceThumbnail extends St.Widget { + _init(metaWorkspace) { + super._init({ + clip_to_allocation: true, + style_class: 'workspace-thumbnail' + }); + this._delegate = this; + this.metaWorkspace = metaWorkspace; this.monitorIndex = Main.layoutManager.primaryIndex; this._removed = false; - this.actor = new St.Widget({ clip_to_allocation: true, - style_class: 'workspace-thumbnail' }); - this.actor._delegate = this; - this._contents = new Clutter.Actor(); - this.actor.add_child(this._contents); + this.add_child(this._contents); - this.actor.connect('destroy', this._onDestroy.bind(this)); + this.connect('destroy', this._onDestroy.bind(this)); this._createBackground(); @@ -308,7 +311,7 @@ var WorkspaceThumbnail = class { } setPorthole(x, y, width, height) { - this.actor.set_size(width, height); + this.set_size(width, height); this._contents.set_position(-x, -y); } @@ -336,7 +339,7 @@ var WorkspaceThumbnail = class { set slidePosition(slidePosition) { this._slidePosition = slidePosition; - this.actor.queue_relayout(); + this.queue_relayout(); } get slidePosition() { @@ -345,7 +348,7 @@ var WorkspaceThumbnail = class { set collapseFraction(collapseFraction) { this._collapseFraction = collapseFraction; - this.actor.queue_relayout(); + this.queue_relayout(); } get collapseFraction() { @@ -446,11 +449,6 @@ var WorkspaceThumbnail = class { this._doAddWindow(metaWin); } - destroy() { - if (this.actor) - this.actor.destroy(); - } - workspaceRemoved() { if (this._removed) return; @@ -475,7 +473,6 @@ var WorkspaceThumbnail = class { } this._windows = []; - this.actor = null; } // Tests if @actor belongs to this workspace and monitor @@ -590,8 +587,7 @@ var WorkspaceThumbnail = class { return false; } -}; -Signals.addSignalMethods(WorkspaceThumbnail.prototype); +}); var ThumbnailsBox = GObject.registerClass( @@ -688,8 +684,8 @@ class ThumbnailsBox extends St.Widget { for (let i = 0; i < this._thumbnails.length; i++) { let thumbnail = this._thumbnails[i]; - let [, h] = thumbnail.actor.get_transformed_size(); - if (y >= thumbnail.actor.y && y <= thumbnail.actor.y + h) { + let [, h] = thumbnail.get_transformed_size(); + if (y >= thumbnail.y && y <= thumbnail.y + h) { thumbnail.activate(time); break; } @@ -769,14 +765,14 @@ class ThumbnailsBox extends St.Widget { if (this._dropPlaceholderPos == 0) targetBase = this._dropPlaceholder.y; else - targetBase = this._thumbnails[0].actor.y; + targetBase = this._thumbnails[0].y; let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE; let length = this._thumbnails.length; for (let i = 0; i < length; i ++) { // Allow the reorder target to have a 10px "cut" into // each side of the thumbnail, to make dragging onto the // placeholder easier - let [, h] = this._thumbnails[i].actor.get_transformed_size(); + let [, h] = this._thumbnails[i].get_transformed_size(); let targetBottom = targetBase + WORKSPACE_CUT_SIZE; let nextTargetBase = targetBase + h + spacing; let nextTargetTop = nextTargetBase - spacing - ((i == length - 1) ? 0 : WORKSPACE_CUT_SIZE); @@ -955,7 +951,7 @@ class ThumbnailsBox extends St.Widget { thumbnail.setPorthole(this._porthole.x, this._porthole.y, this._porthole.width, this._porthole.height); this._thumbnails.push(thumbnail); - this.add_actor(thumbnail.actor); + this.add_actor(thumbnail); if (start > 0 && this._spliceIndex == -1) { // not the initial fill, and not splicing via DND @@ -1289,8 +1285,8 @@ class ThumbnailsBox extends St.Widget { childBox.y1 = y1; childBox.y2 = y1 + portholeHeight; - thumbnail.actor.set_scale(roundedHScale, roundedVScale); - thumbnail.actor.allocate(childBox, flags); + thumbnail.set_scale(roundedHScale, roundedVScale); + thumbnail.allocate(childBox, flags); // We round the collapsing portion so that we don't get thumbnails resizing // during an animation due to differences in rounded, but leave the uncollapsed @@ -1328,7 +1324,7 @@ class ThumbnailsBox extends St.Widget { let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP); this.indicatorY = this._indicator.allocation.y1 + indicatorTopFullBorder; Tweener.addTween(this, - { indicatorY: thumbnail.actor.allocation.y1, + { indicatorY: thumbnail.allocation.y1, time: WorkspacesView.WORKSPACE_SWITCH_TIME / 1000, transition: 'easeOutQuad', onComplete: () => {